﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Workbench.Models;
using SharedGenomics.Workbench.PresentationModel;

namespace SharedGenomics.Workbench.Tests.Models
{
    [TestClass]
    public class KeggPathwayFrequenciesModelTests
    {
        #region Private Members

        private KeggPathwayFrequenciesModel model;

        #endregion

        #region Setup

        [TestInitialize]
        public void Setup()
        {
            this.model = new KeggPathwayFrequenciesModel();
        }

        #endregion

        #region Constructor Tests

        [TestMethod]
        public void ConstructorTest_MaxFrequencyInitiallyZero()
        {
            KeggPathwayFrequenciesModel m = new KeggPathwayFrequenciesModel();
            Assert.AreEqual(0, m.MaxFrequency);
        }

        [TestMethod]
        public void ConstructorTest_CollectionInitiallyEmpty()
        {
            KeggPathwayFrequenciesModel m = new KeggPathwayFrequenciesModel();
            Assert.AreEqual(0, m.Count());
        }

        #endregion

        /// <summary>
        /// This test checks that all pathway frequencies are added to the model
        /// </summary>
        [TestMethod]
        public void LoadPathwayFrequenciesTest_Count()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 1), new KeggPathwayFrequency("pw2", 2) });
            Assert.AreEqual(2, this.model.Count());
        }

        [TestMethod]
        public void LoadPathwayFrequenciesTest_MaxValue()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 4), new KeggPathwayFrequency("pw2", 11) });
            Assert.AreEqual(11, this.model.MaxFrequency);
        }

        /// <summary>
        /// When a collection of pathway frequencies are loaded, when enumerating the model these should be sorted in descending order of frequency
        /// </summary>
        [TestMethod]
        public void LoadPathwayFrequenciesTest_Sorted()
        {
            var frequencies = new List<KeggPathwayFrequency>
            {
                new KeggPathwayFrequency("pw1", 4),
                new KeggPathwayFrequency("pw2", 1),
                new KeggPathwayFrequency("pw3", 3),
                new KeggPathwayFrequency("pw4", 2),
                new KeggPathwayFrequency("pw5", 7)
            };

            this.model.LoadPathwayFrequencies(frequencies);

            //check pathways are sorted in descending order of frequency
            int prevFreq = this.model.First().Frequency;
            foreach (var f in this.model.Skip(1))
            {
                Assert.IsTrue(prevFreq >= f.Frequency);
                prevFreq = f.Frequency;
            }
        }

        /// <summary>
        /// Since the pathway frequencies form is only concerned with display, the model should not check for any duplicated pathway frequencies
        /// </summary>
        [TestMethod]
        public void LoadPathwayFrequenciesTest_DuplicatePathwayNames()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 1), new KeggPathwayFrequency("pw1", 3) });
            Assert.AreEqual(2, this.model.Count());
        }

        /// <summary>
        /// The model should clear the previous pathways when loading a new set of pathway frequencies
        /// </summary>
        [TestMethod]
        public void LoadPathwayFrequenciesTest_ClearsPrevious()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 1) });
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 4), new KeggPathwayFrequency("pw2", 5) });

            Assert.AreEqual(2, this.model.Count());
        }
        
        /// <summary>
        /// Loading null should clear the collection of pathway frequencies rather than throwing an exception
        /// </summary>
        [TestMethod]
        public void LoadPathwayFrequenciesTest_Null_Count()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 1) });
            this.model.LoadPathwayFrequencies(null);

            Assert.AreEqual(0, this.model.Count());
        }

        [TestMethod]
        public void LoadPathwayFrequenciesTest_Null_MaxFrequency()
        {
            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw1", 1) });
            this.model.LoadPathwayFrequencies(null);

            Assert.AreEqual(0, this.model.MaxFrequency);
        }

        [TestMethod]
        public void LoadPathwayFrequenciesTest_RaisedLoadedEvent()
        {
            bool eventRaised = false;
            this.model.PathwayFrequenciesLoaded += (o, e) => { eventRaised = true; };

            this.model.LoadPathwayFrequencies(new[] { new KeggPathwayFrequency("pw", 1) });
            Assert.IsTrue(eventRaised);
        }
    }
}
